/*****************************************************************************
*                     Organizaci�n de Datos - 75.06                          *
*                         C�tedra Lic. Servetto                              *
*            Facultad de Ingenier�a - Universidad de Buenos Aires            *
******************************************************************************/ 

#include <string>
#include "../Comun/Archivo.h"
#include "ArchivoEnMemoria.h"

using namespace std;

namespace ComunPrueba
{

	ArchivoEnMemoria::ArchivoEnMemoria()
	{
		this->primerGrupoId = Comun::NoHayMasGrupos;
		this->proximoGrupoId = 0;

		this->gruposEnMemoria = new map<int, Grupo>();
		
		this->libres = new stack<int>();
		this->libres->push(this->proximoGrupoId);
	};

	ArchivoEnMemoria::~ArchivoEnMemoria()
	{
		delete(this->gruposEnMemoria);
		delete(this->libres);
	};

	int ArchivoEnMemoria::CrearGrupo(Grupo &grupo)
	{
		if (this->primerGrupoId == Comun::NoHayMasGrupos)
			this->primerGrupoId = this->proximoGrupoId;

		grupo.GrupoId = this->TraerIdDeGrupoLibre();
		return grupo.GrupoId;
	};

	CodigoResultado ArchivoEnMemoria::GuardarGrupo(Grupo &grupo, bool omitirSubflujo)
	{
		if (grupo.Registros.size() >= ArchivoEnMemoria::CantidadSobreflujo)
			return Sobreflujo;

		if ((grupo.Registros.size() < ArchivoEnMemoria::CantidadSubflujo) && (!omitirSubflujo))
			return Subflujo;

		this->gruposEnMemoria->insert(*(new pair<int, Grupo>(grupo.GrupoId, grupo)));
		
		return Exito;
	};

	Grupo& ArchivoEnMemoria::LeerGrupo(int grupoId)
	{
		return (*this->gruposEnMemoria->find(grupoId)).second;
	};

	void ArchivoEnMemoria::BorrarGrupo(int grupoId)
	{
		if (grupoId == this->primerGrupoId)
		{
			this->primerGrupoId = this->SiguienteGrupo(grupoId);
		}
		this->gruposEnMemoria->erase(grupoId);
		this->libres->push(grupoId);
	};

	int ArchivoEnMemoria::PrimerGrupo()
	{
		return this->primerGrupoId;
	};

	int ArchivoEnMemoria::SiguienteGrupo(int grupoIdActual)
	{
		IteradorDeGruposEnMemoria grupoSiguiente = this->gruposEnMemoria->find(grupoIdActual)++;

		if (grupoSiguiente == this->gruposEnMemoria->end())
			return Comun::NoHayMasGrupos;
		else
			return (*grupoSiguiente).second.GrupoId;
	};

	int ArchivoEnMemoria::TraerIdDeGrupoLibre()
	{
		if (this->libres->size() > 0)
		{
			int grupoLibre = this->libres->top();
			this->libres->pop();
			return grupoLibre;
		}
		else
		{
			this->proximoGrupoId++;
			return this->proximoGrupoId - 1;
		}
	};
}
